<?php

/**
 * 框架核心文件
 * Created by william
 * Date: 2019-10-05
 * Time: 12:01
 */
if(in_array(RUN_MODE,array('dev','test'))){
    ini_set("display_errors","On");
    error_reporting(E_ALL);
}else{
    ini_set("display_errors","Off");
}
define("FRAMEWORK_DIR",__DIR__);
$composer_autofile = FRAMEWORK_DIR.'/../vendor/autoload.php';
if(is_file($composer_autofile)){
    require $composer_autofile;
}

class Boot{
    /**
     * web模式
     */
    public static function initWeb()
    {
        spl_autoload_register('Loader::autoload'); // 注册自动加载
        //请求的变量过滤
        if($_REQUEST){
            if($_GET){
                foreach($_GET AS $getKey=>&$getValue){
                    if($getKey != 's'){
                        $getValue = safe_escape($getValue);
                    }else{
                        $getValue = uri_safe($getValue);
                    }    
                }
            }
            if($_POST){
                $_POST = safe_escape($_POST);
            }
            $_REQUEST = safe_escape($_REQUEST);
        }
        //cookie过滤
        if($_COOKIE){
            $_COOKIE = safe_escape($_COOKIE);
        }
        $path_info = '';
        $arr_route = [];
        if(!empty($_SERVER["PATH_INFO"])){
            //apache
            $path_info =  $_SERVER["PATH_INFO"];
        }elseif(!empty($_GET['s'])){
            $path_info =  $_GET['s'];
        }
        $path_info = str_replace([$_SERVER['SCRIPT_NAME']],'',$path_info);
        $route_config = load_config('route') ;
        if($route_config && $path_info ){
            foreach($route_config AS $kr=>&$vr){
                preg_match_all("/{$kr}/i",$path_info,$match_arr);
                if(!empty($match_arr[0])){
                    $path_info = $vr;
                    $match_count = count($match_arr);
                    if($match_count > 1){
                        for($i = 1; $i<$match_count;$i++){
                            if(isset($match_arr[$i][0])){
                                $path_info = str_replace(':'.$i,$match_arr[$i][0],$path_info);
                            }
                        }
                        $_GET    = array_merge($_GET,getParamFromUrl($path_info));
                        $_REQUEST = array_merge($_REQUEST,$_GET);
                    }
                    break;
                }
            }
        }
        if(!empty($path_info)){
            //nginx
            $arr_route = explode('/',str_replace($_SERVER['SCRIPT_NAME'],'',$path_info));
            if($arr_route){
                unset($arr_route[0]);
                $arr_route = array_column($arr_route,null);
            }
        }
        $host_config = load_config('host');
        if($host_config){
            foreach($host_config AS $kh =>&$vh){
                //当前访问的域名，不要取$_SERVER['SERVER_NAME']这个变量,这个变量跟服务器配置文件的servername的顺序有关
                if($_SERVER['HTTP_HOST'] == $vh){
                    define('C_MODULE_BIND',$kh);
                    break;
                }
            }
        }

        $route = parseUri($arr_route);

        define('C_MODULE'     ,$route['module']);
        define('C_CONTROLLER',$route['controller']);
        //允许使用.html格式的美化路由
        define('C_ACTION'     , str_replace(['.html','.shtml'],'',$route['action']));
        $controller_dir = $route['controller_dir'] ? $route['controller_dir'] . '/' : '';
        $controller_file = APPLICATION_DIR.C_MODULE.'/controller/'.$controller_dir.ucfirst(C_CONTROLLER).'Controller.php';

        if(!is_file($controller_file)){
            if(!is_file(APPLICATION_DIR.C_MODULE.'/controller/EmptyController.php')){
                redirect('/404.html');
            }
            require APPLICATION_DIR.C_MODULE.'/controller/EmptyController.php';
            $controllerClassName = C_MODULE.'\\controller\\'.'EmptyController';
            
            call_user_func_array([new $controllerClassName,'indexAction'],$_REQUEST);
            exit;
        }
//        require $controller_file;
        $controller_dir_path = $controller_dir ? str_replace("/","\\",$controller_dir) : '';
        $controllerClassName = C_MODULE.'\\controller\\'.$controller_dir_path.ucfirst(C_CONTROLLER).'Controller';
        if(!method_exists($controllerClassName,C_ACTION.'Action')){
            $theme_dir = '';
            if(C_MODULE == 'home'){
                $theme_dir = load_config('globalconfig','theme_name').'/';
            }
            $viewFile = APPLICATION_DIR.C_MODULE.'/view/'.$theme_dir.ucfirst(C_CONTROLLER).'/'.C_ACTION.'.html';
            //只显示纯模板页面
            if(is_file($viewFile)){
                display($viewFile);
                exit;
            }
            ajaxReturn(['msg'=>'method '.$controllerClassName.'/'.C_ACTION.'Action not exist','code'=>-1000]);
        }
        $ret = call_user_func_array([new $controllerClassName,C_ACTION.'Action'],$_REQUEST);
        $ret_type = gettype($ret);
        if(in_array($ret_type,['string','integer','double','NULL'])){
            echo $ret;
        }
    }

    /**
     * 启动命令行模式
     */
    public static function initConsole($argv)
    {
        set_time_limit(0);
        spl_autoload_register('Loader::autoload'); // 注册自动加载
        //命令行模式,例 php console.php demo/hello name=hello value=world
        if(empty($argv[1])){
            consoleReturn( 'controller/action is empty or wrong format');
        }
        $requestUri = $argv[1];
        $arr_route = explode('/',$requestUri);
        $route = parseConsoleUri($arr_route);
        array_shift($argv);
        array_shift($argv);
        $consoleParams     = $argv;
        $consoleParamsNew  = [];
        if($consoleParams){
            foreach($consoleParams AS $kConsole=>&$vConsole){
                $t = explode("=",$vConsole);
                if(count($t) == 2){
                    $consoleParamsNew[$t[0]] = $t[1];
                }
            }
        }

        define('C_MODULE'     ,uri_safe($route['module']) );
        define('C_CONTROLLER',uri_safe($route['controller']));
        //允许使用.html格式的美化路由
        $route['action']       = uri_safe($route['action']);
        define('C_ACTION'     , $route['action']);
        $controller_file = ROOT_DIR.'console/controller/'.ucfirst(C_CONTROLLER).'Controller.php';
        if(!is_file($controller_file)){
            consoleReturn( $controller_file.' not exist!');
        }
//        require $controller_file;
        $controllerClassName = C_MODULE.'\\controller\\'.ucfirst(C_CONTROLLER).'Controller';
        if(!method_exists($controllerClassName,C_ACTION.'Action')){
            echo $controllerClassName.' method '.C_ACTION.'Action not exist!';
            exit;
        }
        $con = new $controllerClassName;
        $conAction = C_ACTION.'Action';
        $ret =  $con->$conAction($consoleParamsNew);
        $ret_type = gettype($ret);
        if(in_array($ret_type,['string','integer','double','NULL'])){
            echo $ret;
        }
//    call_user_func_array([new $controllerClassName,C_ACTION],$consoleParamsNew);
    }
}

/**
 * 自动装载类
 * Class Loader
 */
class Loader
{
    /* 路径映射 */
    public static $includeMap = array(
        'common'          => APPLICATION_DIR  . '../common/',
        'home'             => APPLICATION_DIR  . 'home/',
        'api'             => APPLICATION_DIR  . 'api/',
        'backend'          => APPLICATION_DIR  . 'backend/',
        'console'          => ROOT_DIR.'console/'  ,
        'jimu'          => APPLICATION_DIR  . '../framework/jimu/',
    );
    public static $_loadHistory = [];
    /**
     * 自动加载器
     */
    public static function autoload($class)
    {
        if(isset(self::$_loadHistory[$class])){
            return true;
        }
        $file = self::findFile($class);
        if ($file ) {
            self::$_loadHistory[$class] = $file;
            self::includeFile($file);
        }
        return true;
    }

    /**
     * 解析文件路径
     */
    private static function findFile($class)
    {
        $arr = explode('\\',$class);
        $first = $arr[0];
        array_shift($arr);
        $arrSub = implode(DIRECTORY_SEPARATOR,$arr);
        foreach(self::$includeMap AS $kInclude=>&$vInclude){
            if($kInclude == $first){
                $file = $vInclude.$arrSub.'.php';
                if(is_file($file)){
                    return $file;
                }
            }

        }
        return ''; // 文件标准路径
    }

    /**
     * 引入文件
     */
    private static function includeFile($file)
    {
        if (is_file($file)) {
            include $file;
        }
    }
}

/**
 * 跳转
 * @param $path
 * @param bool $exit
 */
function redirect($path,$exit=true)
{
    //带有http(s)://的链接或者以/开头的站内链接
    if (preg_match('/(http:\/\/)|(https:\/\/)|^(\/)/i', $path)) {
        header("Location:".$path);
    }else{
        $arr = explode('/',$path);
        $arr_num = count($arr);
        if($arr_num >= 3){
            header('Location:'.$path);
        }elseif(count($arr) == 2){
            header('Location:/'.C_MODULE.'/'.$path);
        }else{
            header('Location:/'.C_MODULE.'/'.C_CONTROLLER.'/'.$path);
        }
    }

    if($exit){
        exit;
    }
}

/**
 * 解析web路由
 * @param array $arr_route
 * @return mixed
 */
function parseUri($arr_route=[])
{
    $get_vars_pos = 0;
    $default_module = load_config('globalconfig','default_module');
    $arr_num = count($arr_route);
    if($arr_num){
        //路由的方法里带有参数
        $ask_pos = stripos($arr_route[$arr_num-1],"?");
        if( $ask_pos !== false){
            $arr_route[$arr_num-1] = substr($arr_route[$arr_num-1],0,$ask_pos);
        }
    }
    $route['controller_dir'] = '';
    //绑定域名
    if(defined('C_MODULE_BIND')){
        if(!empty($arr_route[0]) && !empty($arr_route[1]) ){
            $con_arr = [];
            if(stripos($arr_route[0],'-') !== false){
                $con_arr = explode('-',$arr_route[0]);
            }
            $route['module']      = C_MODULE_BIND;
            $route['controller_dir'] = $con_arr ? uri_safe($con_arr[0]) : '';
            $route['controller'] = $con_arr ? uri_safe($con_arr[1]) : $arr_route[0];
            $route['action']      = uri_safe($arr_route[1]);
            $get_vars_pos = 3;
        }elseif(!empty($arr_route[0]) && empty($arr_route[1])){
            $route['module']      = C_MODULE_BIND;
            $route['controller'] = uri_safe($arr_route[0]);
            $route['action']      = 'index';
        }else{
            //首页
            $route['module']      = C_MODULE_BIND;
            $route['controller']  = 'index';
            $route['action']      = 'index';
        }

    }else{ //没有绑定域名
        if(!empty($arr_route[0]) && !empty($arr_route[1]) && !empty($arr_route[2]) ){
            $con_arr = [];
            if(stripos($arr_route[1],'-') !== false){
                $con_arr = explode('-',$arr_route[1]);
            }
            $route['module']      = uri_safe($arr_route[0]);
            $route['controller_dir'] = $con_arr ? uri_safe($con_arr[0]) : '';
            $route['controller'] = $con_arr ? uri_safe($con_arr[1]) : $arr_route[1];
            $route['action']      = uri_safe($arr_route[2]);
            /**如果要在重写的url里带参数请使用
            格式1 http://dev.jimu.cc/home/index/add/a/5/b/2
            格式2 http://dev.jimu.cc/home/passport.auth/index/a/10/b/5
             */
            $get_vars_pos = 4;
        }elseif(!empty($arr_route[0]) && !empty($arr_route[1]) && empty($arr_route[2])){
            $route['module']      = $default_module;
            $route['controller'] = uri_safe($arr_route[0]);
            $route['action']      = uri_safe($arr_route[1]);
        }elseif(!empty($arr_route[0]) && empty($arr_route[1])){
            $route['module']      = $default_module;
            $route['controller'] = uri_safe($arr_route[0]);
            $route['action']      = 'index';
        }else{
            //首页
            $route['module']      = $default_module;
            $route['controller']  = 'index';
            $route['action']      = 'index';
        }
    }

    if($get_vars_pos){
        $get_vars = getParamsFromUrlArr($arr_route,$get_vars_pos);
        if($get_vars){
            $_GET = array_merge($_GET,$get_vars);
            $_REQUEST = array_merge($_REQUEST,$_GET);
        }
    }
    return $route;
}

/**
链接如下http://dev.jimu.cc/home/passport/auth/index/a/10/b/9/c/1
 从一个url数组中解析出get变量
 例如:
Array
(
[0] =>
[1] => home
[2] => passport
[3] => auth
[4] => index
[5] => a
[6] => 10
[7] => b
[8] => 9
[9] => c
[10] => 1
)
返回:
Array
(
[a] => 10
[b] => 9
[c] => 1
)
 * @param array $arr
 * @param int $pos 第一个参数在数组中的位置
 * @return array
 */
function getParamsFromUrlArr($arr,$pos=3)
{
    $ret =[];
    if(empty($pos) || empty($arr)){
        return $ret;
    }
    $len = count($arr);
    if($len<=$pos){
        return $ret;
    }
    if(isset($arr[$pos])){
        for ($x=$pos; $x<=$len; $x+=2) {
            $valKey =  $x+1;
            if(!empty($arr[$x]) && isset($arr[$valKey])){
                $ret[$arr[$x]] = $arr[$valKey];
            }
        }
    }
    return $ret;
}

/**
 * 将字符串参数变为数组
 *$url = 'http://www.baidu.com/index.php?m=content&c=index&a=lists&catid=6&area=0&author=0&h=0®ion=0&s=1&page=1';
 * @param $query
 * @return array array (size=10)
'm' => string 'content' (length=7)
'c' => string 'index' (length=5)
'a' => string 'lists' (length=5)
'catid' => string '6' (length=1)
'area' => string '0' (length=1)
'author' => string '0' (length=1)
'h' => string '0' (length=1)
'region' => string '0' (length=1)
's' => string '1' (length=1)
'page' => string '1' (length=1)
 */
function getParamFromUrl($url)
{
    $params = array();
    $arr = parse_url($url);
    if($arr['query']){
        $queryParts = explode('&', $arr['query']);
        foreach ($queryParts as &$param) {
            $item = explode('=', $param);
            if(isset($item[0]) && isset($item[1])){
                $params[$item[0]] = $item[1];
            }
        }
    }

    return $params;
}

function parseConsoleUri($arr_route=[]){
    if(!empty($arr_route[0]) && !empty($arr_route[1]) ){
        $route['module']      = 'console';
        $route['controller'] = uri_safe($arr_route[0]);
        $route['action']      = uri_safe($arr_route[1]);
    }else{
        //首页
        $route['module']      = 'console';
        $route['controller']  = 'index';
        $route['action']      = 'index';
    }
    return $route;
}

function json($params=[])
{
    return json_encode($params,JSON_UNESCAPED_UNICODE);
}

function ajaxReturn($params)
{
    echo json($params);
    exit;
}

//命令行模式下的输出
function consoleReturn($params,$exit=true)
{
    if(is_string($params)){
        echo $params;
    }else{
        print_r($params);
    }
    if($exit){
        exit;
    }
}

function is_cli_mode() {
    $sapi_type = php_sapi_name();
    if (isset($sapi_type) && substr($sapi_type, 0, 3) == 'cli') {
        return true;
    } else {
        return false;
    }
}

/**
 * 调试函数,以文件的形式把变量记录到一个文件里
 * author: chenwei
 * @param var $text 要记录到文件的变量
 * @param bool $save_req_params 是否需要记录request提交的变量
 * @param string $debug_sign 调试的变量标志符，例如'UserModel'.__LINE__
 * */
function debug_dump($text,$save_req_params=false,$debug_sign='')
{
    $logdir=APPLICATION_DIR.'../public/log/';
    if(!is_dir($logdir))return false;
    if(!is_writeable($logdir))@chmod($logdir,0777);
    if(!is_writeable($logdir))return false;
    $debug_info = debug_backtrace();
    $arr_file_info = pathinfo($debug_info[0]['file']);
    $debug_message = $arr_file_info['filename']. '__'.$debug_info[0]['line'];
    $file_mark = $debug_sign=='' ? $debug_message : $debug_sign;
    $logfilename = $logdir.'dump_' . date('Ymd_').$file_mark . '.txt';
    $_stamp = '';
    if(!is_cli_mode()){
        $_stamp .= "-------------------------------------------------------------".PHP_EOL;
        $_stamp .= $_SERVER['REQUEST_URI'].':'.date('Y-m-d H:i:s').PHP_EOL;
        $_stamp .= $file_mark.PHP_EOL;
        if($save_req_params){
            $_stamp .= json_encode($_REQUEST,JSON_UNESCAPED_UNICODE).PHP_EOL;
        }
        $_stamp .= "-------------------------------------------------------------".PHP_EOL;
    }
    ob_start();
    echo '<pre>';
    print_r($text);
    $str = ob_get_contents();
    $str .= PHP_EOL;
    $str .= $_stamp;
    $str = preg_replace("/^<pre>/",'',$str);
    ob_end_clean();

    file_put_contents($logfilename, $str, FILE_APPEND);
}

/**
 * 调试打印在页面上
 * author: chenwei
 * */
function debug_print($text,$is_exit=true)
{
    $_stamp = '';
    $_stamp .= "-------------------------------------------------------------".PHP_EOL;
    $_stamp .= $_SERVER['REQUEST_URI'].PHP_EOL;
    $_stamp .= "-------------------------------------------------------------".PHP_EOL;
    ob_start();
    echo '<pre>';
    print_r($text);
    $str = ob_get_contents();
    $str .= "\n\n";
    $str .= $_stamp;
    ob_end_clean();
    echo $str;
    if($is_exit)exit;
}

function uri_safe($str)
{
    $find = ['../','..','./'];
    $replace = ['','',''];
    return str_replace($find,$replace,$str);
}

/* 进行安全字段和xss跨站脚本攻击过滤(通用版)
@param $string 被过滤的字符串
@param $allow 允许的字符
*/
function safe_escape($string,$allow=[])
{
    $search = array (
        '/</i',
        '/>/i',
        '/\">/i',
        '/\bunion\b/i',
        '/\.\.\/?/i',
        //严格过滤SQL关键字
        //'/^select|insert|and|or|create|update|delete|alter|count|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/i',
        "/\b(select|insert|update|delete|and|alter|count)\b/i", //采用判断单词边界方式过滤SQL操作关键字
        '/load_file(\s*(\/\*.*\*\/)?\s*)+\(/i',
        '/into(\s*(\/\*.*\*\/)?\s*)+outfile/i',
        '/\bor\b/i',
    );
    $replace = array (
        '&lt;',
        '&gt;',
        '&quot;&gt;',
        'union&nbsp;',
        '',
        '',
        'load_file&nbsp; (',
        'into&nbsp; outfile',
        'or&nbsp;',
    );
    if (is_array ( $string )) {
        $key = array_keys ( $string );
        $size = sizeof ( $key );
        for($i = 0; $i < $size; $i ++) {
            $string [$key [$i]] = str_replace ( array (
                '\n',
                '\r'
            ), array (
                chr ( 10 ),
                chr ( 13 )
            ), preg_replace ( $search, $replace, $string [$key [$i]] ) );
            $string [$key [$i]] = remove_xss ( $string [$key [$i]] ,$allow);
            $string [$key [$i]] = daddslashes($string [$key [$i]]);
        }
    } else {
        $string = str_replace ( array (
            '\n',
            '\r'
        ), array (
            chr ( 10 ),
            chr ( 13 )
        ), preg_replace ( $search, $replace, $string ) );
        $string = remove_xss ( $string,$allow );
        $string = daddslashes($string);
    }
    return $string;
}

function remove_xss($val,$allow=[])
{
    $val = preg_replace ( '/([\x00-\x08\x0b-\x0c\x0e-\x19])/', '', $val );

    $search = 'abcdefghijklmnopqrstuvwxyz';
    $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $search .= '1234567890!@#$%^&*()';
    $search .= '~`";:?+/={}[]-_|\'\\';
    for($i = 0; $i < strlen ( $search ); $i ++) {

        $val = preg_replace ( '/(&#[xX]0{0,8}' . dechex ( ord ( $search [$i] ) ) . ';?)/i', $search [$i], $val );

        $val = preg_replace ( '/(&#0{0,8}' . ord ( $search [$i] ) . ';?)/', $search [$i], $val );
    }

    $ra1 = array (
        'javascript',
        'vbscript',
        'expression',
        'applet',
        'meta',
        'xml',
        'blink',
        'script',
        'object',
        'video',
        'iframe',
        'frame',
        'frameset',
        'ilayer',
        'bgsound'
    );

    $ra2 = array (
        'onabort',
        'onactivate',
        'onafterprint',
        'onafterupdate',
        'onbeforeactivate',
        'onbeforecopy',
        'onbeforecut',
        'onbeforedeactivate',
        'onbeforeeditfocus',
        'onbeforepaste',
        'onbeforeprint',
        'onbeforeunload',
        'onbeforeupdate',
        'onblur',
        'onbounce',
        'oncellchange',
        'onchange',
        'onclick',
        'oncontextmenu',
        'oncontrolselect',
        'oncopy',
        'oncut',
        'ondataavailable',
        'ondatasetchanged',
        'ondatasetcomplete',
        'ondblclick',
        'ondeactivate',
        'ondrag',
        'ondragend',
        'ondragenter',
        'ondragleave',
        'ondragover',
        'ondragstart',
        'ondrop',
        'onerror',
        'onerrorupdate',
        'onfilterchange',
        'onfinish',
        'onfocus',
        'onfocusin',
        'onfocusout',
        'onhelp',
        'onkeydown',
        'onkeypress',
        'onkeyup',
        'onlayoutcomplete',
        'onload',
        'onlosecapture',
        'onmousedown',
        'onmouseenter',
        'onmouseleave',
        'onmousemove',
        'onmouseout',
        'onmouseover',
        'onmouseup',
        'onmousewheel',
        'onmove',
        'onmoveend',
        'onmovestart',
        'onpaste',
        'onpropertychange',
        'onreadystatechange',
        'onreset',
        'onresize',
        'onresizeend',
        'onresizestart',
        'onrowenter',
        'onrowexit',
        'onrowsdelete',
        'onrowsinserted',
        'onscroll',
        'onselect',
        'onselectionchange',
        'onselectstart',
        'onstart',
        'onstop',
        'onsubmit',
        'onunload'
    );
    $ra = array_merge ( $ra1, $ra2 );
    if(!empty($allow)){
        //哪些标签是可选择保留不过滤的
        $ra = array_merge(array_diff($ra, $allow));
    }
    $found = true;
    while ( $found == true ) {
        $val_before = $val;
        for($i = 0; $i < sizeof ( $ra ); $i ++) {
            $pattern = '/';
            for($j = 0; $j < strlen ( $ra [$i] ); $j ++) {
                if ($j > 0) {
                    $pattern .= '(';
                    $pattern .= '(&#[xX]0{0,8}([9ab]);)';
                    $pattern .= '|';
                    $pattern .= '|(&#0{0,8}([9|10|13]);)';
                    $pattern .= ')*';
                }
                $pattern .= $ra [$i] [$j];
            }
            $pattern .= '/i';
            $replacement = substr ( $ra [$i], 0, 2 ) . ' ' . substr ( $ra [$i], 2 );
            $val = preg_replace ( $pattern, $replacement, $val );
            if ($val_before == $val) {

                $found = false;
            }
        }
    }
    return $val;
}

//防注入
function daddslashes(&$var)
{
    if (! get_magic_quotes_gpc ()) {
        if (is_array ( $var )) {
            foreach ( $var as $key => &$val ) {
                $var [$key] = daddslashes ( $val );
            }
        } else {
            $var = addslashes ( $var );
        }
    }
    return $var;
}

/**
 * 模板引擎初始化
 * @param $tpl
 * @param array $params
 * @param int $cache_lifetime
 * @return array
 */
function tplInit($tpl,$params=[],$cache_lifetime=0)
{

    require FRAMEWORK_DIR.'/../libs/smarty/libs/Smarty.class.php';
    $smarty = new Smarty;

    $arr_tpl = explode("/",$tpl);

    $theme_dir = '';
    if(C_MODULE == 'home'){
        $theme_dir = load_config('globalconfig','theme_name').DIRECTORY_SEPARATOR;
    }
    $tplName = '';
    $base_dir = APPLICATION_DIR.C_MODULE.DIRECTORY_SEPARATOR.'view'.DIRECTORY_SEPARATOR.$theme_dir;
    if(stripos($tpl,'.html') !== false){
        $tplName = $tpl;
    }else{
        if(empty($tpl) || count($arr_tpl) == 1 ){
            $smarty->template_dir = $base_dir.ucfirst(C_CONTROLLER).DIRECTORY_SEPARATOR;//模板目录,当前控制器名称的文件夹
            if(count($arr_tpl) == 1){
                $tplName = $arr_tpl[0];
            }
        }elseif(count($arr_tpl) == 2 ){
            $smarty->template_dir = $base_dir.ucfirst($arr_tpl[0]).DIRECTORY_SEPARATOR;//模板目录
            $tplName = $arr_tpl[1];
        }
    }

    $smarty->compile_dir = APPLICATION_DIR.DIRECTORY_SEPARATOR.C_MODULE.DIRECTORY_SEPARATOR.'compile/';//编译目录

    //$smarty->force_compile = true;
    $smarty->debugging = false;
    if($cache_lifetime){
        $smarty->caching = true;
        $smarty->cache_lifetime = $cache_lifetime;
    }
    $smarty->left_delimiter = '<{';
    $smarty->right_delimiter = '}>';
    if($params){
        foreach($params AS $keyParam=>&$valParam){
            $smarty->assign($keyParam, $valParam);
        }
    }
    if(empty($tpl)) $tplName = C_ACTION;
    if(stripos($tplName,'.html') === false){
        $tplName .= '.html';
    }
    return ['tpl_obj'=>$smarty,'tpl_name'=>$tplName];
}

/**
 * 显示模板
 * @param $tpl 模板文件
 */
function display($tpl='',$params=[],$cache_lifetime=0)
{
    $ret = tplInit($tpl,$params,$cache_lifetime);
    return $ret['tpl_obj']->display($ret['tpl_name']);
}

/**
 * 获取模板文件解析后的内容
 * @param $tplPath
 * @return mixed
 */
/**
 * 获取模板文件解析后的内容
 * @param $tpl 模板文件
 * @params $params 参数
 * @param $cache_lifetime 缓存时间
 * @return mixed
 */
function fetch($tpl='',$params=[],$cache_lifetime=0)
{
    $ret = tplInit($tpl,$params,$cache_lifetime);
    if(isset($params['cache_id'])){
        return $ret['tpl_obj']->fetch($ret['tpl_name'].'.html',$params['cache_id']);
    }
    return $ret['tpl_obj']->fetch($ret['tpl_name']);
}


/**
 * 加载配置文件
 * @param string $file 配置文件
 * @param string $key  要获取的配置荐
 * @param string $default  默认配置数值。当获取配置项目失败时该值发生作用。
 * @param boolean $reload 强制重新加载。
 */
function load_config($file, $key = '', $default = '', $reload = false)
{
    static $configs = array();
    if (!$reload && isset($configs[$file])) {
        if (empty($key)) {
            return $configs[$file];
        } elseif (isset($configs[$file][$key])) {
            return $configs[$file][$key];
        } else {
            return $default;
        }
    }
    $filepath = APPLICATION_DIR.'../config/'.RUN_MODE.DIRECTORY_SEPARATOR.$file.'.php';
    if (is_file($filepath)) {
        $configs[$file] = include $filepath;
    }
    if (empty($key)) {
        return $configs[$file];
    } elseif (isset($configs[$file][$key])) {
        return $configs[$file][$key];
    } else {
        return $default;
    }
}

/**
 * 加载model文件函数
 * @param string $classname 类名
 * @param string $path 扩展地址
 * @param intger $initialize 是否初始化
 */
function load_model($classname, $path = '', $initialize = 1)
{
    static $classes = array();
    if (empty($path)) $path = C_MODULE.DIRECTORY_SEPARATOR.'model';

    $key = $path.'\\'.$classname;
    if (isset($classes[$key])) {
        if (!empty($classes[$key])) {
            return $classes[$key];
        }
    }
    if (is_file(APPLICATION_DIR.$path.DIRECTORY_SEPARATOR.$classname.'.php')) {
        include APPLICATION_DIR.$path.DIRECTORY_SEPARATOR.$classname.'.php';
        $name = str_replace('\/','\\',$path.'\\'.$classname);
        if ($initialize) {
            $classes[$key] = new $name;
        } else {
            $classes[$key] = true;
        }
        return $classes[$key];
    } else {
        return false;
    }
}

/**
 * 加载class文件函数
 * @param string $classname 类名
 * @param string $path 扩展地址
 * @param intger $initialize 是否初始化
 */
function load_class($classname, $path = '', $initialize = 1)
{
    static $classes = array();
    if (empty($path)) $path = 'libs'.DIRECTORY_SEPARATOR.'classes';

    $key =  $path.$classname;
    if (isset($classes[$key])) {
        if (!empty($classes[$key])) {
            return $classes[$key];
        }
    }
    if (is_file(APPLICATION_DIR.'../'.$path.DIRECTORY_SEPARATOR.$classname.'.class.php')) {
        include APPLICATION_DIR.'../'.$path.DIRECTORY_SEPARATOR.$classname.'.class.php';
        $name = '\\'.$classname;
        if ($initialize) {
            $classes[$key] = new $name;
        } else {
            $classes[$key] = true;
        }
        return $classes[$key];
    } else {
        return false;
    }
}

/**
 * 是否post请求
 * @return bool
 */
function is_post()
{
    return $_POST ? true :false;
}